home *** CD-ROM | disk | FTP | other *** search
- /* cfengine for GNU
-
- Copyright (C) 1995
- Free Software Foundation, Inc.
-
- This file is part of GNU cfengine - written and maintained
- by Mark Burgess, Dept of Computing and Engineering, Oslo College,
- Dept. of Theoretical physics, University of Oslo
-
- This program is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published by the
- Free Software Foundation; either version 2, or (at your option) any
- later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
-
- */
-
-
- #include "cf.defs.h"
- #include "cf.extern.h"
-
-
- /*********************************************************************/
- /* */
- /* Tidy object */
- /* */
- /*********************************************************************/
-
- RecursiveHomeTidy(name,level,tp)
-
- char *name;
- int level;
- struct Tidy *tp;
-
- { struct stat statbuf;
- DIR *dirh;
- struct dirent *dirp;
- char pcwd[bufsize];
- time_t ticks;
-
- if (strlen(name) == 0)
- {
- name = "/";
- }
-
- Debug2("HomeTidy: Opening %s\n",name);
-
- if ((dirh = opendir(name)) == NULL)
- {
- sprintf(OUTPUT,"Can't open directory %s\n",name);
- CfLog(cferror,OUTPUT,"");
- return;
- }
-
- if (level == 2)
- {
- strcpy(VLOGFILE,name);
- strcat(VLOGFILE,"/.cfengine.rm");
-
- /* Unlink here to avoid an exploit which could be used to overwrite a system
- file with root privileges. */
-
- if (unlink(VLOGFILE) == -1)
- {
- sprintf(OUTPUT,"Pre-existing object %s could not be removed\n",VLOGFILE);
- CfLog(cfverbose,OUTPUT,"unlink");
- }
-
- if ((VLOGFP = fopen(VLOGFILE,"w")) == NULL) /* log deleted files for each user */
- {
- sprintf(OUTPUT,"Couldn't open a file %s\n",VLOGFILE);
- CfLog(cferror,OUTPUT,"fopen");
- VLOGFP = stderr;
- }
- else
- {
- ticks = time((time_t *)NULL);
- fprintf(VLOGFP,"This file is generated by cfengine %s\n",VERSION);
- fprintf(VLOGFP,"It contains a log of the files which have been tidied.\n");
- fprintf(VLOGFP,"The time of writing is %s\n",ctime(&ticks));
- fprintf(VLOGFP,"If you have any questions about this, send them to %s.\n",VSYSADM);
- fprintf(VLOGFP,"-(Start transcript)---------------\n");
- }
- }
-
- for (dirp = readdir(dirh); dirp != NULL; dirp = readdir(dirh))
- {
- if (!SensibleFile(dirp->d_name,name,NULL))
- {
- continue;
- }
-
- if (IgnoreFile(name,dirp->d_name,NULL))
- {
- continue;
- }
-
- strcpy(pcwd,name); /* Assemble pathname */
- AddSlash(pcwd);
-
- if (BufferOverflow(pcwd,dirp->d_name))
- {
- return;
- }
-
- strcat(pcwd,dirp->d_name);
-
- if (TRAVLINKS)
- {
- if (stat(pcwd,&statbuf) == -1)
- {
- sprintf(OUTPUT,"Can't stat %s\n",pcwd);
- CfLog(cferror,OUTPUT,"stat");
- continue;
- }
- }
- else
- {
- if (lstat(pcwd,&statbuf) == -1)
- {
- if (DEBUG || D2 || VERBOSE)
- {
- sprintf(OUTPUT,"Can't stat %s\n",pcwd);
- CfLog(cferror,OUTPUT,"lstat");
- if (readlink(pcwd,VBUFF,bufsize) != -1)
- {
- sprintf(OUTPUT,"File is link to -> %s\n",VBUFF);
- CfLog(cferror,OUTPUT,"");
- }
- }
- continue;
- }
- }
-
-
- if (S_ISDIR(statbuf.st_mode))
- {
- if (IsMountedFileSystem(&statbuf,pcwd,1))
- {
- continue;
- }
- else
- {
- RecursiveHomeTidy(pcwd,level+1,tp);
- }
- }
- else
- {
- TidyHomeFile(pcwd,dirp->d_name,&statbuf);
- }
- }
-
- if (level == 2)
- {
- fclose(VLOGFP);
- chmod(VLOGFILE,DEFAULTMODE);
- }
-
- closedir(dirh);
- }
-
-
- /*********************************************************************/
-
- TidyHomeFile(path,name,statbuf)
-
- char *path;
- char *name;
- struct stat *statbuf;
-
- /* Tidy a file if it's past its sell-by date in kB, and if
- it is greater than the specified size. Don't need an OR,
- since size age can just be set to zero. */
-
- { struct Tidy *tp;
- struct TidyPattern *tlp;
- short savetravlinks, savekilloldlinks;
-
- for (tp = VTIDY; tp != NULL; tp=tp->next)
- {
- if (tp->tidylist == NULL) /* used to eliminate non-home searches */
- {
- continue;
- }
-
- for (tlp = tp->tidylist; tlp != NULL; tlp=tlp->next)
- {
- if (IsExcluded(tlp->classes))
- {
- continue;
- }
-
- savetravlinks = TRAVLINKS;
- savekilloldlinks = KILLOLDLINKS;
-
- ResetOutputRoute(tlp->log,tlp->inform);
-
- if (tlp->travlinks == 'T')
- {
- TRAVLINKS = true;
- }
- else if (tlp->travlinks == 'F')
- {
- TRAVLINKS = false;
- }
- else if (tlp->travlinks == 'K')
- {
- KILLOLDLINKS = true;
- }
-
- TRAVLINKS = savetravlinks;
-
- if (WildMatch(tlp->pattern,name) && CheckHomeSubDir(path,tp->path,tp->recurse))
- {
- DoTidyFile(path,name,tlp,statbuf,CF_USELOGFILE);
- }
-
- ResetOutputRoute('d','d');
- }
- }
-
- TRAVLINKS = savetravlinks;
- KILLOLDLINKS = savekilloldlinks;
- }
-
-
- /*********************************************************************/
-
- RecursiveTidySpecialArea(name,tp,maxrecurse)
-
- char *name;
- struct Tidy *tp;
- int maxrecurse;
-
- { struct stat statbuf,topstatbuf;
- DIR *dirh;
- struct dirent *dirp;
- char pcwd[bufsize];
- int is_dir,level,nostat=false;
-
- bzero(&statbuf,sizeof(statbuf));
-
- if (maxrecurse == -1)
- {
- Debug2("MAXRECURSE ran out, quitting at %s\n",name);
- return;
- }
-
- if (IgnoreFile(name,"",NULL))
- {
- Debug2("cfengine: Ignoring directory %s\n",name);
- return;
- }
-
- if (strlen(name) == 0) /* Check for root dir */
- {
- name = (char *) malloc(2);
- name[0] = '/';
- name[1] = '\0';
- }
-
- if (maxrecurse == tp->recurse)
- {
- if (lstat(name,&topstatbuf) == -1)
- {
- if (DEBUG || D2 || VERBOSE)
- {
- sprintf(OUTPUT,"Can't stat %s\n",name);
- CfLog(cferror,OUTPUT,"");
-
- if (readlink(name,VBUFF,bufsize) != -1)
- {
- sprintf(OUTPUT,"File is link to -> %s\n",VBUFF);
- CfLog(cferror,OUTPUT,"");
- }
- }
- return;
- }
- }
-
- if ((dirh = opendir(name)) == NULL)
- {
- sprintf(OUTPUT,"Can't open directory [%s]\n",name);
- CfLog(cferror,OUTPUT,"opendir");
- return;
- }
-
- Debug("Tidy: opening dir %s\n",name);
-
- for (dirp = readdir(dirh); dirp != NULL; dirp = readdir(dirh))
- {
- if (!SensibleFile(dirp->d_name,name,NULL))
- {
- continue;
- }
-
- if (IgnoreFile(name,dirp->d_name,NULL))
- {
- continue;
- }
-
- strcpy(pcwd,name); /* Assemble pathname */
- AddSlash(pcwd);
-
- if (BufferOverflow(pcwd,dirp->d_name))
- {
- return;
- }
-
- strcat(pcwd,dirp->d_name);
-
- if (stat(pcwd,&statbuf) == -1)
- {
- nostat=true;
- }
-
- if (S_ISDIR(statbuf.st_mode))
- {
- is_dir = true;
- }
- else
- {
- is_dir = false;
- }
-
- if (!TRAVLINKS || nostat) /* Don't try to travlinks where we can't stat destination - just remove them */
- {
- if (lstat(pcwd,&statbuf) == -1)
- {
- if (DEBUG || D2 || VERBOSE)
- {
- sprintf(OUTPUT,"Can't stat %s\n",pcwd);
- CfLog(cferror,OUTPUT,"lstat");
- if (readlink(pcwd,VBUFF,bufsize) != -1)
- {
- sprintf(OUTPUT,"File is link to -> %s\n",VBUFF);
- CfLog(cferror,OUTPUT,"");
- }
- }
- continue;
- }
- }
-
- level = tp->recurse - maxrecurse;
-
- if (S_ISDIR(statbuf.st_mode)) /* note lstat above! */
- {
- if (IsMountedFileSystem(&statbuf,pcwd,1))
- {
- continue;
- }
- else
- {
- RecursiveTidySpecialArea(pcwd,tp,maxrecurse-1);
- }
-
- TidyParticularFile(pcwd,dirp->d_name,tp,&statbuf,is_dir,level);
- }
- else
- {
- TidyParticularFile(pcwd,dirp->d_name,tp,&statbuf,is_dir,level);
- }
- }
-
- closedir(dirh);
-
- if (maxrecurse == tp->recurse)
- {
- Debug("Checking tidy topmost directory %s\n",name);
-
- TidyParticularFile(name,ReadLastNode(name),tp,&topstatbuf,true,tp->recurse);
- }
- }
-
- /*********************************************************************/
-
- TidyParticularFile(path,name,tp,statbuf,is_dir,level)
-
- char *path, *name;
- struct Tidy *tp;
- struct stat *statbuf;
- int level,is_dir;
-
- { struct TidyPattern *tlp;
-
- Debug2("TidyParticularFile(%s,%s)\n",path,name);
-
- if (tp->tidylist == NULL)
- {
- return;
- }
-
- for (tlp = tp->tidylist; tlp != NULL; tlp=tlp->next)
- {
- ResetOutputRoute(tlp->log,tlp->inform);
-
- if (S_ISLNK(statbuf->st_mode) && is_dir && (tlp->dirlinks == 'k') && (tlp->rmdirs == 'f')) /* Keep links to directories */
- {
- ResetOutputRoute('d','d');
- continue;
- }
-
- if (is_dir && tlp->rmdirs == 'f') /* not allowed to rmdir */
- {
- ResetOutputRoute('d','d');
- continue;
- }
-
- if ((level == tp->recurse) && tlp->rmdirs == 's') /* rmdir subdirs only */
- {
- ResetOutputRoute('d','d');
- continue;
- }
-
- if (level > tlp->recurse && tlp->recurse != INFINITERECURSE)
- {
- Debug2("[PATTERN %s RECURSE ENDED at %d(%d) BEFORE MAXVAL %d]\n",tlp->pattern,
- level,tlp->recurse,tp->recurse);
- ResetOutputRoute('d','d');
- continue;
- }
-
- if (IsExcluded(tlp->classes))
- {
- ResetOutputRoute('d','d');
- continue;
- }
-
- if (! WildMatch(tlp->pattern,name))
- {
- ResetOutputRoute('d','d');
- continue;
- }
-
- if (S_ISLNK(statbuf->st_mode) && is_dir && (tlp->dirlinks == 't'))
- {
- Debug("Link to directory, dirlinks= says delete these\n");
- }
- else if (is_dir && !EmptyDir(path))
- {
- sprintf(OUTPUT,"Non-empty directory %s, skipping..\n",path);
- CfLog(cfinform,OUTPUT,"");
- ResetOutputRoute('d','d');
- continue;
- }
-
- Debug2("Matched %s to %s in %s\n",name,tlp->pattern,path);
- DoTidyFile(path,name,tlp,statbuf,CF_NOLOGFILE);
- ResetOutputRoute('d','d');
- }
- }
-
- /*********************************************************************/
- /* Level 2 */
- /*********************************************************************/
-
- DoTidyFile(path,name,tlp,statbuf,logging_this)
-
- char *path, *name;
- struct TidyPattern *tlp;
- struct stat *statbuf;
- short logging_this;
-
- { time_t nowticks, fileticks;
- int size_match = false, age_match = false;
-
- Debug2("DoTidyFile(%s,%s)\n",path,name);
-
- nowticks = time((time_t *)NULL); /* cmp time in days */
-
- switch (tlp->searchtype)
- {
- case 'a': fileticks = statbuf->st_atime;
- break;
- case 'm': fileticks = statbuf->st_mtime;
- break;
- case 'c': fileticks = statbuf->st_ctime;
- break;
- default: printf("cfengine: Internal error in DoTidyFile()\n");
- break;
- }
-
- if (nowticks-fileticks < 0) /* shouldn't happen */
- {
- sprintf(OUTPUT,"ALERT: atime for %s is in the future. Check system clock!\n",path);
- CfLog(cfinform,OUTPUT,"");
- return;
- }
-
- if (tlp->size == CF_EMPTYFILE)
- {
- if (statbuf->st_size == 0)
- {
- size_match = true;
- }
- else
- {
- size_match = false;
- }
- }
- else
- {
- size_match = (tlp->size <= statbuf->st_size);
- }
-
- age_match = tlp->age*ticksperday <= (nowticks-fileticks);
-
- if (age_match && size_match)
- {
- if (logging_this)
- {
- fprintf(VLOGFP,"cf: rm %s\n",path);
- }
-
- if (! DONTDO)
- {
- if (S_ISDIR(statbuf->st_mode))
- {
- if (rmdir(path) == -1)
- {
- CfLog(cferror,"","unlink");
- }
- else
- {
- AddMultipleClasses(tlp->defines);
- }
- }
- else
- {
- if (unlink(path) == -1)
- {
- sprintf(OUTPUT,"Couldn't unlink %s tidying\n",path);
- CfLog(cfverbose,OUTPUT,"unlink");
- }
- else
- {
- AddMultipleClasses(tlp->defines);
- }
- }
-
- sprintf(OUTPUT,"Deleting %s\n",path);
- CfLog(cfinform,OUTPUT,"");
- sprintf(OUTPUT,"Size=%d bytes, %c-age=%d days\n",
- statbuf->st_size,tlp->searchtype,(nowticks-fileticks)/ticksperday);
- CfLog(cfverbose,OUTPUT,"");
- }
- else
- {
- printf("%s: want to remove %s\n",VPREFIX,path);
- }
- }
- else
- {
- Debug2("(No age match)\n");
- }
- }
-
-
- /*********************************************************************/
-
- DeleteTidyList(list)
-
- struct TidyPattern *list;
-
- {
- if (list != NULL)
- {
- DeleteTidyList(list->next);
- list->next = NULL;
-
- if (list->classes != NULL)
- {
- free (list->classes);
- }
-
- free((char *)list);
- }
- }
-
-
-
-
-
-
-
-